home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Sample Code / Snippets / QuickDraw / Out of This GWorld / out.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-15  |  15.9 KB  |  482 lines  |  [TEXT/KAHL]

  1.  
  2. /****************************************************************************/
  3. /*                                                                            */
  4. /*    Application:    Out of This GWorld                                        */
  5. /*                                                                            */
  6. /*    Description:    This application demonstrates one method to                */
  7. /*                    produce animation on the Macintosh using QuickDraw's    */
  8. /*                    palette manager animation routines.  The app simply        */
  9. /*                    creates an offscreen image, copies it to the            */
  10. /*                    screen's window, then calls AnimatePalette()            */
  11. /*                    every cycle through the eventloop.  To provide the        */
  12. /*                    fastest possible animation, the image is only            */
  13. /*                    created and copied once from the offscreen GWorld.        */
  14. /*                    The actual animation is produced by shifting the        */
  15. /*                    color entries within its colortable forward or            */
  16. /*                    backward one index.  Also the cTable is divided            */
  17. /*                    and shifted in two separate groups to simulate            */
  18. /*                    objects moving at different speeds.                        */
  19. /*                                                                            */
  20. /*    Files:            out.c        - offscreen and color routines                */
  21. /*                    draw.c        - custom drawing routines                    */
  22. /*                    events.c    - standard event handling routines            */
  23. /*                    menu.c        - standard menu bar routines                */
  24. /*                                                                            */
  25. /*    Programmer:        Edgar Lee                                                */
  26. /*    Organization:    Apple Computer, Inc.                                    */
  27. /*    Department:        Developer Technical Support, DTS                        */
  28. /*    Language:        C (Think C version 4.0.4)                                */
  29. /*    Date Created:    8-13-91                                                    */
  30. /*                                                                            */
  31. /****************************************************************************/
  32.  
  33. #include "out.h"
  34.  
  35. /*******************************/
  36. /* Global Variable Definitions */
  37. /*******************************/
  38.  
  39. WindowPtr        gWindow;                /* Main Display Window */
  40. CTabHandle        gCTable;                /* Window & offscreen Colortable */
  41. GWorldPtr        gGWorld;                /* Offscreen GWorld */
  42. PixMapHandle    gPixMap;                /* PixMap of the GWorld */
  43. PaletteHandle    gPalette;                /* Window & offscreen Palette */
  44.  
  45. int                gCurrentPat = 1;        /* Current Test Pattern */
  46. int                gCurrentMove = STOP;    /* Current State of Animation */
  47. int                gCurrentDir = FORWARD;    /* Current Direction to Shift Palette Colors */
  48. int                gCurrentColor = COLOR;    /* Current Colors: mixed or gray */
  49.  
  50. main()
  51. {
  52.     MaxApplZone();            /* Increase application heap. */
  53.  
  54.     initMac();                /* Do standard mac initializations. */
  55.     initVariables();        /* Initialize the colortable. */
  56.     
  57.     createWindow();
  58.     createPalette();
  59.     createGWorld();
  60.  
  61.     createImage();            /* Create the current image offscreen. */
  62.     drawImage();            /* Copybits the offscreen image into the window. */
  63.  
  64.     pollEvents();            /* Handle any events & update the palette. */
  65. }
  66.  
  67. void initMac()
  68. {
  69.     /*********************************/
  70.     /* Standard Initialization Calls */
  71.     /*********************************/
  72.     
  73.     InitGraf( &thePort );
  74.     InitFonts();
  75.     InitWindows();
  76.     InitMenus();
  77.     TEInit();
  78.     InitDialogs( nil );
  79.     InitCursor();
  80.     FlushEvents( 0, everyEvent );
  81.     
  82.     setUpMenus();
  83. }
  84.  
  85. void initVariables()
  86. {
  87.     /********************************************************************/
  88.     /* Allocate memory for the colortable.  Since ColorTable already    */
  89.     /*    contains one ColorSpec, allocate (TOTALCOLORS - 1) ColorSpec's.    */
  90.     /*    One ColorSpec is required for each entry.                        */
  91.     /********************************************************************/
  92.         
  93.     gCTable = (CTabHandle)NewHandle( sizeof( ColorTable ) +
  94.                 ((TOTALCOLORS - 1) * sizeof( ColorSpec )));
  95. }
  96.  
  97. void createWindow()
  98. {
  99.     Rect wBounds;
  100.  
  101.     /*****************************************************************/    
  102.     /* Create and center the destination window in the main monitor. */
  103.     /*****************************************************************/
  104.     
  105.     SetRect( &wBounds, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
  106.     gWindow = NewCWindow( 0L, &wBounds, "\pOut of This GWorld", true, noGrowDocProc,
  107.                             (WindowPtr)-1L, true, 0L );
  108.     
  109.     /**************************************************************/
  110.     /* Display the main window and assign it as the current port. */
  111.     /**************************************************************/
  112.     
  113.     ShowWindow( gWindow );
  114.     SetPort( gWindow );
  115. }
  116.  
  117. void createPalette()
  118. {
  119.     /********************************************************************/
  120.     /* Allocate a palette for color animation.  Using pmExplicit as the    */
  121.     /*    usage, tells QD that the index values in the palette are more    */
  122.     /*    important than the rgb values stored at that index.  This is    */
  123.     /*    necessary since the animation in this application is simulated    */
  124.     /*    by shifting the colors at each palette index.                    */
  125.     /********************************************************************/
  126.     
  127.     gPalette = NewPalette( TOTALCOLORS, nil, pmAnimated + pmExplicit, 0 );
  128.     
  129.     /************************************************/
  130.     /* Define the rgb values at each palette index. */
  131.     /************************************************/
  132.     
  133.     defineColorPalette();
  134.     
  135.     /******************************************/
  136.     /* Attach the palette to the main window. */
  137.     /******************************************/
  138.     
  139.     SetPalette( gWindow, gPalette, true );
  140. }
  141.  
  142. void createGWorld()
  143. {
  144.     int            i;
  145.     Rect        gBounds;
  146.     CGrafPtr    currentPort;
  147.     GDHandle    currentDevice;
  148.     
  149.     /*************************************************/
  150.     /* Define the size of the GWorld's bounding box. */
  151.     /*************************************************/
  152.     
  153.     SetRect( &gBounds, 0, 0, gWindow->portRect.right - gWindow->portRect.left,
  154.                             gWindow->portRect.bottom - gWindow->portRect.top );
  155.  
  156.     /********************************************************************************/
  157.     /* Convert the palette to a colortable before explicitly setting bit 14 in        */
  158.     /*    the ctFlags field of the colortable.  This tells the colortable to refer    */
  159.     /*    to the palette indexes instead of its rgb values.  Again, this is             */
  160.     /*    necessary since the animation is performed by altering the palette.            */
  161.     /********************************************************************************/
  162.         
  163.     Palette2CTab( gPalette, gCTable );
  164.     (**gCTable).ctFlags |= 0x4000;
  165.  
  166.     /************************************************************************/
  167.     /* Make sure each value field of the colortable is assigned to the        */
  168.     /*    corresponding entry in the palette and make sure the ctSeed field    */
  169.     /*    is given a unique value.                                            */
  170.     /************************************************************************/
  171.     
  172.     for (i = 0; i < TOTALCOLORS; i++)
  173.         (**gCTable).ctTable[i].value = i;
  174.     (**gCTable).ctSeed = GetCTSeed();
  175.     
  176.     /*************************************************************************/
  177.     /* Allocate a new GWorld for the offscreen drawing and store its PixMap. */
  178.     /*************************************************************************/
  179.     
  180.     NewGWorld( &gGWorld, 8, &gBounds, gCTable, nil, 0 );
  181.     gPixMap = GetGWorldPixMap( gGWorld );
  182. }
  183.  
  184. void updatePalette()
  185. {
  186.     /******************************************************************************/
  187.     /* Convert the altered colortable to a palette, then animate all its entries. */
  188.     /******************************************************************************/
  189.  
  190.     Palette2CTab( gPalette, gCTable );
  191.     AnimatePalette( gWindow, gCTable, 0, 0, TOTALCOLORS );
  192. }
  193.  
  194. void defineColorPalette()
  195. {
  196.     int i;
  197.     
  198.     gCurrentColor = COLOR;
  199.  
  200.     /***********************************************************************/
  201.     /* Define the first 8 palette entries with primary & secondary colors. */
  202.     /***********************************************************************/
  203.     
  204.     setRGB( 0, 0, 0, 0 );            /* black */
  205.     setRGB( 1, 0, 255, 0 );            /* green */
  206.     setRGB( 2, 0, 255, 255 );        /* cyan */
  207.     setRGB( 3, 0, 0, 255 );            /* blue */
  208.     setRGB( 4, 255, 0, 255 );        /* magenta */
  209.     setRGB( 5, 255, 0, 0 );            /* red */
  210.     setRGB( 6, 255, 255, 0 );        /* yellow */
  211.     setRGB( 7, 255, 255, 255 );        /* white */
  212.  
  213.     /*******************************************************************/
  214.     /* Define shades of the previous colors for the remaining entries. */
  215.     /*******************************************************************/
  216.  
  217.     for (i = 8; i < 48; i++)                                        /* greens */
  218.         setRGB( i, 0, 10 + ((i - 8) * 6), 0 );
  219.         
  220.     for (i = 48; i < 88; i++)                                        /* blues */
  221.         setRGB( i, 0, 0, 10 + ((i - 48) * 6) );
  222.         
  223.     for (i = 88; i < 128; i++)                                        /* reds */
  224.         setRGB( i, 10 + ((i - 88) * 6), 0, 0 );
  225.     
  226.     for (i = 128; i < 168; i++)                                        /* magentas */
  227.         setRGB( i, 10 + ((i - 128) * 6), 0, 10 + ((i - 128) * 6) );
  228.     
  229.     for (i = 168; i < 208; i++)                                        /* yellows */
  230.         setRGB( i, 10 + ((i - 168) * 6), 10 + ((i - 168) * 6), 0 );
  231.     
  232.     for (i = 208; i < 248; i++)                                        /* cyans */
  233.         setRGB( i, 0, 10 + ((i - 208) * 6), ((i - 208) * 6) );
  234. }
  235.  
  236. void defineGrayPalette()
  237. {
  238.     int i;
  239.     int shade;
  240.  
  241.     gCurrentColor = GRAY;
  242.     
  243.     /*******************************************************/
  244.     /* Define all the palette entries with shades of gray. */
  245.     /*******************************************************/
  246.  
  247.     for (i = 1; i < 7; i++)
  248.     {
  249.         shade = i * 42;
  250.         setRGB( i, shade, shade, shade );
  251.     }
  252.     
  253.     for (i = 8, shade = 10; i < 248; i++)
  254.     {
  255.         setRGB( i, shade, shade, shade );
  256.         shade += 12;
  257.         
  258.         if ((i - 8) % 20 == 0)
  259.             shade = 10;
  260.     }
  261. }
  262.  
  263. void setRGB( index, r, g, b )
  264. int    index;
  265. int    r, g, b;
  266. {
  267.     RGBColor aColor;
  268.     
  269.     /***********************************************************************/
  270.     /* Set the rgb values for the palette color stored at the index value. */
  271.     /***********************************************************************/
  272.     
  273.     aColor.red = r * SUN2MAC;        /* All colors were defined using    */
  274.     aColor.green = g * SUN2MAC;        /*    SUN computer raster values.        */
  275.     aColor.blue = b * SUN2MAC;
  276.     
  277.     SetEntryColor( gPalette, index, &aColor );
  278. }
  279.  
  280. void setColor( index )
  281. int index;
  282. {
  283.     RGBColor aColor;
  284.     
  285.     /********************************************************/
  286.     /* Get the rgb values stored at the index value in the    */
  287.     /*    palette, then use it as the foreground color.        */
  288.     /********************************************************/
  289.                     
  290.     GetEntryColor( gPalette, index, &aColor );
  291.     RGBForeColor( &aColor );
  292. }
  293.  
  294. void createImage()
  295. {
  296.     CGrafPtr    currentPort;
  297.     GDHandle    currentDevice;
  298.     RGBColor    aColor;
  299.     
  300.     /******************************************************************************/
  301.     /* Store the current port and device before switching to the offscreen world. */
  302.     /******************************************************************************/
  303.     
  304.     GetGWorld( ¤tPort, ¤tDevice );
  305.     
  306.     /****************************************************************************/
  307.     /* Switch to the offscreen GWorld then lock the offscreen buffer in memory. */
  308.     /****************************************************************************/
  309.  
  310.     SetGWorld( gGWorld, nil );
  311.     LockPixels( gPixMap );
  312.     
  313.     /************************************************/
  314.     /* Set the background color to black then erase    */
  315.     /*    the PixMap's bounding box in the GWorld.    */
  316.     /************************************************/
  317.     
  318.     GetEntryColor( gPalette, 0, &aColor );
  319.     RGBBackColor( &aColor );
  320.     EraseRect( &(**gPixMap).bounds );
  321.  
  322.     /*************************************************************/
  323.     /* Draw a 1 pixel wide white border along the PixMap's edge. */
  324.     /*************************************************************/
  325.     
  326.     drawWindowBorder();
  327.  
  328.     /*************************************************************************/
  329.     /* Depending on the current test pattern, create an image in the PixMap. */
  330.     /*************************************************************************/
  331.  
  332.     if (gCurrentPat == 1)
  333.         createColorScale();
  334.     else if (gCurrentPat == 2)
  335.         createColorWheels();
  336.     else if (gCurrentPat == 3)
  337.         createColorRings();
  338.     else if (gCurrentPat == 4)
  339.         createColorGears();
  340.     else if (gCurrentPat == 5)
  341.         createColorCurves();
  342.     else if (gCurrentPat == 6)
  343.         createColorBalls();
  344.     else if (gCurrentPat == 7)
  345.         createColorWave();
  346.     else if (gCurrentPat == 8)
  347.         createColorText();
  348.     else
  349.         doAbout();                /* Treat the About message as a test pattern. */
  350.     
  351.     /********************************************************************/
  352.     /* After drawing the image, unlock the offscreen buffer in memory    */
  353.     /*    and set the port and device back to the window's.                */
  354.     /********************************************************************/
  355.  
  356.     UnlockPixels( gPixMap );
  357.     SetGWorld( currentPort, currentDevice );
  358. }
  359.  
  360. void drawWindowBorder()
  361. {
  362.     /********************************************************************/
  363.     /* Set the foreground color to white before drawing a 1 pixel wide    */
  364.     /*    frame around the PixMap's bounding box.                            */
  365.     /********************************************************************/
  366.     
  367.     setColor( 7 );
  368.     PenSize( 1, 1 );
  369.     MoveTo( 0, 0 );
  370.     LineTo( 0, (**gPixMap).bounds.bottom - 1 );
  371.     LineTo( (**gPixMap).bounds.right - 1, (**gPixMap).bounds.bottom - 1 );
  372.     LineTo( (**gPixMap).bounds.right - 1, 0 );
  373. }
  374.  
  375. void drawImage()
  376. {
  377.     /***********************************************************/
  378.     /* Transfer the contents of the PixMap to the main window. */
  379.     /***********************************************************/
  380.  
  381.     CopyBits( (BitMap*)*gPixMap, &gWindow->portBits, &(**gPixMap).bounds,
  382.                 &gWindow->portRect, srcCopy, 0l);
  383. }
  384.  
  385. void animateCTable()
  386. {
  387.     static int        counter = 0;
  388.     RGBColor         aColor;
  389.  
  390.     /**************************************************************************/
  391.     /* Convert the Palette to a colortable before shifting the color entries. */
  392.     /**************************************************************************/
  393.     
  394.     Palette2CTab( gPalette, gCTable );    
  395.  
  396.     /************************************************************************/
  397.     /* Depending on the current direction, shift 239 palette entries either    */
  398.     /*    ahead 1 or behind 1 index.  Store the first or last entry before    */
  399.     /*    shifting to avoid overwriting its rgb values.                        */
  400.     /************************************************************************/
  401.  
  402.     if (gCurrentDir == FORWARD)
  403.     {
  404.         aColor = (**gCTable).ctTable[247].rgb;
  405.         BlockMove( &(**gCTable).ctTable[8].value, &(**gCTable).ctTable[9].value,
  406.                     239 * sizeof(ColorSpec) );
  407.         (**gCTable).ctTable[8].rgb = aColor;
  408.     }
  409.     else
  410.     {
  411.         aColor = (**gCTable).ctTable[8].rgb;
  412.         BlockMove( &(**gCTable).ctTable[9].value, &(**gCTable).ctTable[8].value,
  413.                     239 * sizeof(ColorSpec) );
  414.         (**gCTable).ctTable[247].rgb = aColor;
  415.     }
  416.     
  417.     /**************************************************************/
  418.     /* Shift the first 5 colortable entries once every 6 updates. */
  419.     /**************************************************************/
  420.     
  421.     if (counter == 0)
  422.     {
  423.         aColor = (**gCTable).ctTable[1].rgb;
  424.         BlockMove( &(**gCTable).ctTable[2].value, &(**gCTable).ctTable[1].value,
  425.                     5 * sizeof(ColorSpec) );
  426.         (**gCTable).ctTable[6].rgb = aColor;
  427.     }
  428.  
  429.     /********************************************************/
  430.     /* Update the window's colors by passing the new        */
  431.     /*    colortable as the srcCTab field of AnimatePalette.    */
  432.     /********************************************************/
  433.     
  434.     AnimatePalette( gWindow, gCTable, 0, 0, TOTALCOLORS );
  435.     
  436.     /**********************************************/
  437.     /* Increment the counter by 1 on each update. */
  438.     /**********************************************/
  439.     
  440.     counter = (counter + 1) % 6;
  441. }
  442.  
  443. void doAbout()
  444. {
  445.     Rect        rect;
  446.     PicHandle    thePict;
  447.     int            width, height;
  448.     
  449.     /*******************************************************/
  450.     /* Load the About picture stored in the resource fork. */
  451.     /*******************************************************/
  452.  
  453.     thePict = (PicHandle)GetResource( 'PICT', 128 );
  454.     
  455.     /************************************************/
  456.     /* Define the rect used to enclose the picture. */
  457.     /************************************************/
  458.  
  459.     width = (**thePict).picFrame.right - (**thePict).picFrame.left;
  460.     height = (**thePict).picFrame.bottom - (**thePict).picFrame.top;
  461.  
  462.     SetRect( &rect, (WWIDTH - width) / 2, (WHEIGHT - height) / 2, 
  463.                     ((WWIDTH - width) / 2) + width, ((WHEIGHT - height) / 2 ) + height );
  464.  
  465.     /*********************************/
  466.     /* Draw the picture in the rect. */
  467.     /*********************************/
  468.  
  469.     DrawPicture( thePict, &rect );
  470.     ReleaseResource( thePict );
  471. }
  472.  
  473. void cleanUp()
  474. {
  475.     /*****************************************************************************/
  476.     /* Free the memory set aside for the GWorld and main window before exitting. */
  477.     /*****************************************************************************/
  478.  
  479.     DisposeGWorld( gGWorld );
  480.     DisposeWindow( gWindow );
  481.     ExitToShell();
  482. }